﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using HtmlAgilityPack;

namespace SSO
{
    public class Program
    {
        static void Main(string[] args)
        {
            ServicePointManager.ServerCertificateValidationCallback += ServerCertificateValidationCallback;
            var cert = GetCert();

            //try
            //{
                // 1 [GET] idp (sf)
                var r1 = HttpBot.Get("https://accounts.sap.com/saml2/idp/usso/sap?sp=www.successfactors.com");
                Debug.Assert(r1.Status == 302, "r1 fail");

                // 2 [GET] idp (saml)
                var r2 = HttpBot.Get(r1.Location, cert, r1.Cookie);
                Debug.Assert(r2.Status == 200, "r2 fail");
                var s2 = Analyze(r2);
                var newCookie = MergeCookie(r1, r2);

                // 3 [POST] idp
                var r3 = HttpBot.Post(s2.Location, cert, newCookie, s2.Body);
                Debug.Assert(r3.Status == 200, "r3 fail");
                var s3 = Analyze(r3);

                // 4 [POST] sf
                var r4 = HttpBot.Post(s3.Location, null, null, s3.Body);
                Debug.Assert(r4.Status == 302 && !r4.Location.Contains("login"), "r4 fail");

                // 5 [GET] test
                var r5 = HttpBot.Get("https://performancemanager5.successfactors.eu/xi/ui/edu/pages/prevewProfile.xhtml?selected_user=90191&selected_view=43", null, r4.Cookie);
                Debug.Assert(r5.Status == 200, "[GET] test fail");
            //}
            //catch (Exception e)
            //{
            //    Console.WriteLine(e.Message);
            //    throw;
            //}

        }

        private static string MergeCookie(HttpResult r1, HttpResult r2)
        {
            var c1 = r1.Cookie.Split(';').First();
            var c2 = r2.Cookie.Split(';').First();
            return string.Join(";", c1, c2);
        }

        public static HttpResult Analyze(HttpResult input)
        {
            HttpResult rs = new HttpResult();

            var doc = new HtmlDocument();
            doc.LoadHtml(input.Body);

            //var form = doc.GetElementbyId("samlResponse");
            var form = doc.DocumentNode.SelectSingleNode("//form");
            var hidden = doc.DocumentNode.SelectSingleNode("//input");

            rs.Location = form.Attributes["action"].Value;
            rs.Body = hidden.Attributes["name"].Value + '=' + encodeURIComponent(hidden.Attributes["value"].Value);

            rs.Cookie = input.Cookie;
            return rs;
        }

        private static string encodeURIComponent(string text)
        {
            return text.Replace("+", "%2B").Replace("/", "%2F").Replace("=", "%3D");
        }

        private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        private static X509Certificate GetCert()
        {
            //X509Store store = new X509Store(StoreLocation.CurrentUser);
            //store.Open(OpenFlags.ReadOnly);
            //X509Certificate2 cert = store.Certificates[99];
            X509Certificate2 cert = new X509Certificate2("my.cer");
            

            return cert;
        }

    }
}
